/**
 * Copyright (C) 2008 Christopher Allen Ogden
 *
 *     This file is part of Odysi.
 *
 *  Odysi is free software: you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  Odysi is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with Odysi.  If not, see <http://www.gnu.org/licenses/>.
 */

#pragma once
#include "uncopyable.h"
#include "database.h"

/**
 * Stores a database statement.
 *
 * @author  Ogden, Chris
 */
class Statement: public Uncopyable
{
    public:
        /**
         * Constructor.
         *
         * @param db    The database.
         * @param query The query to perform.
         */
        Statement(Database &db, const std::string &query):_db(&db),_stmt(NULL)
        {
            setQuery(query);
        }

        /**
         * Constructor.
         *
         * @param db    The database.
         */
        Statement(Database &db):_db(&db),_stmt(NULL)
        {
        }

        /**
         * Set query.
         *
         * @param query             The query to perform.
         * @throws runtime_error    If the query cannot be set.
         */
        void setQuery(const std::string &query)
        {
            sqlite3_finalize(_stmt);
            if(sqlite3_prepare_v2(_db->get(), query.c_str(), -1, &_stmt, NULL) != SQLITE_OK)
            {
                throw std::runtime_error(_db->getError());
            }
        }

        /**
         * Destructor.
         */
        ~Statement()
        {
            sqlite3_finalize(_stmt);
        }

        /**
         * Step the statement.
         *
         * @return  The status of the query.
         */
        int step(void)
        {
            return sqlite3_step(_stmt);
        }

        /**
         * Bind integer.
         *
         * @param pos               The position.
         * @param value             The value.
         * @throws runtime_error    If the bind doesn't work.
         */
        void bind(int pos, int value)
        {
            if(sqlite3_bind_int(_stmt, pos, value) != SQLITE_OK)
            {
                throw std::runtime_error(_db->getError());
            }
        }

        /**
         * Get an integer.
         *
         * @param pos   The position.
         * @return      The integer.
         */
        int getInt(int pos)
        {
             return sqlite3_column_int(_stmt, pos);
        }

        /**
         * Get the statement handle.
         *
         * @return  The statement handle.
         */
        sqlite3_stmt *get(void)
        {
            return _stmt;
        }
    private:
        Statement();

        sqlite3_stmt *_stmt;
        Database *_db;
};
